
package com.daify.threadlearn.chapter01.lock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * ReentrantLock 锁的使用
 * @author daify
 * @date 2019-06-18 10:45
 **/
public class ReentrantLockTest {

    private ReentrantLock lock = new ReentrantLock();

    /**
     * 非公平策略的RenntrantLock
     */
    private ReentrantLock nonfairSync = new ReentrantLock(false);

    /**
     * 公平策略的RenntrantLock
     */
    private ReentrantLock fairSync = new ReentrantLock(true);


    /**
     * 锁的简单用法
     */
    public Thread getDefThread () {
        return new Thread(new Runnable() {
            @Override
            public void run() {
                // 获取锁
                lock.lock();
                try {
                    Thread.sleep(1000);
                    System.out.println("do some things");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    // 释放锁
                    lock.unlock();
                }
            }
        });
    }
    
    public void defLock () {
        Thread t = getDefThread();
        t.start();
    }

    /**
     * 若当下不能取得lock，thread就会放弃，
     */
    public Thread getTryLock () {
        return new Thread(new Runnable() {
            @Override
            public void run() {
                if (lock.tryLock()) {
                    try {
                        System.out.println(Thread.currentThread().getName() + "得到了锁.");
                        Thread.sleep(1000);
                    } catch (InterruptedException e1) {
                        System.out.println(Thread.currentThread().getName() + "是否获得锁，" + lock.isHeldByCurrentThread());
                        System.out.println(Thread.currentThread().getName() + " interrupted.");
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        System.out.println(Thread.currentThread().getName() + "释放了锁.");
                        lock.unlock();
                    }
                } else {
                    System.out.println(Thread.currentThread().getName() + "获取锁失败.");
                }
            }

        });
    }
    
    public void tryLockTest() {
        Thread t = getTryLock();
        Thread t2 = getTryLock();
        t.setName("线程A");
        t2.setName("线程B");
        t.start();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t2.start();
        t2.interrupt();

    }

    /**
     * 若当下不能取得lock，thread就会放弃，
     * 可以设置一个超时时间参数，等待多久获取不到锁就放弃
     */
    public Thread getTryLockTime () {
        return new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    if (lock.tryLock(10, TimeUnit.SECONDS)) {
                        try {
                            System.out.println(Thread.currentThread().getName() + "得到了锁.");
                            Thread.sleep(1000);
                        } catch (InterruptedException e1) {
                            System.out.println(Thread.currentThread().getName() + "是否获得锁，" + lock.isHeldByCurrentThread());
                            System.out.println(Thread.currentThread().getName() + " interrupted.");
                        } catch (Exception e) {
                            e.printStackTrace();
                        } finally {
                            System.out.println(Thread.currentThread().getName() + "释放了锁.");
                            lock.unlock();
                        }
                    } else {
                        System.out.println(Thread.currentThread().getName() + "获取锁失败.");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        });
    }

    public void tryLockTimeTest() {
        Thread t = getTryLockTime();
        Thread t2 = getTryLockTime();
        t.setName("线程A");
        t2.setName("线程B");
        t.start();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t2.start();
        t2.interrupt();


    }



    /**
     * 线程假如使用lockInterruptibly获得锁，这个时候当线程被interrupt的时候，
     * 会抛出InterruptedException异常，此时线程被唤醒并要求处理此异常。
     * 阻塞线程可以相应中断，而运行的线程在不可以中断
     */
    public Thread getLockInterruptibly () {
        return new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    lock.lockInterruptibly();
                    Thread.sleep(5000);
                    System.out.println(Thread.currentThread().getName() + "得到了锁.");
                } catch (InterruptedException e1) {
                    System.out.println(Thread.currentThread().getName() + "是否获得锁，" + lock.isHeldByCurrentThread());
                    System.out.println(Thread.currentThread().getName() + " interrupted.");
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (lock.isHeldByCurrentThread()) {
                        System.out.println(Thread.currentThread().getName() + "释放了锁.");
                        lock.unlock();
                    }
                }
            }

        });
    }

    public void lockInterruptiblyTest() {
        Thread t = getLockInterruptibly();
        Thread t2 = getLockInterruptibly();
        t.setName("线程A");
        t2.setName("线程B");
        t.start();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t2.start();
        // t2.interrupt();
    }

    public static void main(String[] args) {
        ReentrantLockTest test = new ReentrantLockTest();
        test.lockInterruptiblyTest();
    }
    
}
